using System;
using System.Diagnostics;

namespace Dida
{
	public class OrientedBox
	{
		/// <summary>
		/// The matrix that transforms the [-1,-1,-1]-[1,1,1] box to
		/// this oriented box.
		/// </summary>
		Matrix4 mat;

		public OrientedBox(Box box)
		{
			mat = Matrix4.GetScaleMatrix(box.Extends) *
				Matrix4.GetTranslationMatrix(box.Center);
		}

		/// <summary>
		/// Creates an oriented box, from the given axis aligned box, rotated by
		/// the given rotation, around the box' center.
		/// </summary>
		/// <param name="box">The source axis aligned box.</param>
		/// <param name="rotation">The rotation that should be applied to 
		/// get the oriented box. This rotation is applied around the center of
		/// the box.</param>
		public OrientedBox(Box box, EulerRot rotation)
		{
			mat = Matrix4.GetScaleMatrix(box.Extends) *
				rotation.Matrix *
				Matrix4.GetTranslationMatrix(box.Center);
		}

		public OrientedBox(Box box, SimpleTransform transform)
		{
			mat = Matrix4.GetScaleMatrix(box.Extends) *
				Matrix4.GetTranslationMatrix(box.Center) *
				transform.ToMatrix();
		}

		public Plane GetFacePlane(int i)
		{
			Debug.Assert(i >= 0 && i < 6, "The index should be 0 <= i < 6");

			Plane ret = new Plane();
			ret.normal = mat.GetBaseVector(i / 2);
			ret.dist = ret.normal.Len;
			ret.normal /= ret.dist;
			if ((i & 1) != 0)
				ret.normal = -ret.normal;

			Vector3D translation = new Vector3D(mat.rows[0].w, mat.rows[1].w, mat.rows[2].w);
			ret.dist -= Vector3D.DotProduct(ret.normal, translation);

			return ret;
		}

		public Box AxisAlignedBoundingBox
		{
			get
			{
				Box ret = Box.NullBox;
				for (int i = 0; i < 8; i++)
				{
					Vector3D corner = new Vector3D(
						(i & 1) != 0 ? 1 : -1,
						(i & 2) != 0 ? 1 : -1,
						(i & 4) != 0 ? 1 : -1);
					corner = mat.Transform(corner);

					ret.Expand(corner);
				}
				return ret;
			}
		}
	}
}